﻿using GrapeCity.Forguncy.Commands;
using GrapeCity.Forguncy.Plugin;
using Neo4JConnector.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Neo4JConnector
{
    [Icon("pack://application:,,,/Neo4JConnector;component/Resources/Icon.png")]
    [Category("neo4j图数据库")]
    [OrderWeight(10)]
    public class QueryNodes : BaseNeo4JOp, IServerCommandParamGenerator
    {

        [FormulaProperty]
        [DisplayName("节点的标签")]
        [Description("类似于数据库中的表，用于对节点进行分类。")]
        [OrderWeight(100)]
        [SearchableProperty]
        public object LabelExpr { get; set; }

        [FormulaProperty]
        [DisplayName("OrderBy：排序字段（ASC升序）")]
        [OrderWeight(110)]
        [SearchableProperty]
        public object SortAsc { get; set; }


        [FormulaProperty]
        [DisplayName("OrderBy：排序字段（DESC降序）")]
        [OrderWeight(115)]
        [SearchableProperty]
        public object SortDesc { get; set; }


        [FormulaProperty]
        [DisplayName("Skip：跳过")]
        [Description("返回的路径中最多包含多少个节点。")]
        [OrderWeight(120)]
        [SearchableProperty]
        public object Skip { get; set; } = 0;


        [FormulaProperty]
        [DisplayName("Limit：数量限制")]
        [Description("返回的路径中最多包含多少个节点。")]
        [OrderWeight(121)]
        [SearchableProperty]
        public object Limit { get; set; } = 100;

        [OrderWeight(300)]
        [DisplayName("点击设置节点的查询条件")]
        [Description("AND：全部查询条件均满足才能匹配。")]
        [ListProperty]
        public List<QueryConditionObject> Conditions { get; set; }


        [DisplayName("将节点保存到变量")]
        [Description("符合条件的节点数组，虽然仅列出了id，但仍然可以直接用.propertyName的方法读取该节点的所有属性。")]
        [OrderWeight(999)]
        [ResultToProperty]
        public string ResultInParamater { get; set; } = "NodeList";

        public override async Task<ExecuteResult> ExecuteAsync(IServerCommandExecuteContext dataContext)
        {
            var label = (await dataContext.EvaluateFormulaAsync(LabelExpr))?.ToString() ?? "";

            if (string.IsNullOrEmpty(label))
            {
                throw new Exception("节点的标签不能为空。");
            }

            if (!Validators.IsValidLabel(label))
                throw new Exception("节点的标签包含非法字符，仅支持字母数字和下划线，且需要以字母开头。");

            var limit = int.TryParse((await dataContext.EvaluateFormulaAsync(Limit))?.ToString() ?? "100", out var l) ? l : 100;
            var skip = int.TryParse((await dataContext.EvaluateFormulaAsync(Skip))?.ToString() ?? "0", out var s) ? s : 0;
            var sortAsc = (await dataContext.EvaluateFormulaAsync(SortAsc))?.ToString() ?? null;
            var sortDesc = (await dataContext.EvaluateFormulaAsync(SortDesc))?.ToString() ?? null;

            List<QueryConditionObject> conds = [];

            if (Conditions != null)
            {
                foreach (var c in Conditions)
                {
                    conds.Add(await c.Evaluate(dataContext));
                }
            }

            var client = await getClient(dataContext);
            var data = await client.QueryEntities(label, new EntityQueryOptions()
            {
                Filters = conds,
                Limit = limit,
                Skip = skip,
                Ascending = string.IsNullOrEmpty(sortAsc),
                OrderBy = sortAsc ?? sortDesc
            });

            if (!string.IsNullOrEmpty(ResultInParamater))
            {
                dataContext.Parameters[ResultInParamater] = data;
            }

            return new ExecuteResult();
        }

        public override string ToString()
        {
            return "neo4j：查询节点";
        }

        public IEnumerable<GenerateParam> GetGenerateParams()
        {
            yield return new GenerateListParam()
            {
                ParamName = this.ResultInParamater,
                Description = "符合条件的节点",
                ParamScope = CommandScope.All,
                ItemProperties = new List<string>() {
                    "id"
                }
            };
        }
    }
}
